package com.gitee.wsl.ext.map.bikey


import com.gitee.wsl.collections.map.bikey.BiKey
import com.gitee.wsl.func.BiFunction


/**
 * If the specified bikey is not already associated with a value associates
 * it with the given non-null value. Otherwise, replaces the associated
 * value with the results of the given remapping function, or removes if the
 * result is `null`. This method may be of use when combining multiple
 * mapped values for a bikey.
 *
 *
 *
 * If the function returns `null` the mapping is removed. If the
 * function itself throws an (unchecked) exception, the exception is
 * rethrown, and the current mapping is left unchanged.
 *
 * @param row
 * row with which the specified value is to be associated
 * @param column
 * column with which the specified value is to be associated
 * @param value
 * the non-null value to be merged with the existing value
 * associated with the bikey or, if no existing value, to be
 * associated with the key
 * @param remappingFunction
 * the function to recompute a value if present
 * @return the new value associated with the specified bikey, or null if no
 * value is associated with the key
 * @throws NullPointerException
 * if the specified key is null or the value or
 * remappingFunction is null
 */
fun <R, C, V> MutableMap<BiKey<R, C>,V>.merge(row: R, column: C, value: V, remappingFunction: BiFunction<in V, in V, out V>): V {
    val oldValue: V? = get(row, column)
    var newValue = value
    if (oldValue != null) {
        newValue = remappingFunction.apply(oldValue, value)
    }
    if (newValue == null) {
        remove(row, column)
    } else {
        put(row, column, newValue)
    }
    return newValue
}